package com.accessibleworlds.blind;

import com.accessibleworlds.blind.MultitouchGestureListener.GestureType;
import android.content.Context;
import android.util.AttributeSet;
import android.util.FloatMath;
import android.view.MotionEvent;
import android.widget.LinearLayout;

/**
 * Captures the multitouch gestures performed on the given area. 
 * Activities including this view must implement the MultitouchGestureListener interface.
 * 
 * @author Ayberk Özgür
 *
 */
public class MultitouchGestureView extends LinearLayout{
	private float lastX, lastY;
	private float beginX, beginY;
	private int oneFingerEvents, twoFingerEvents, moreFingerEvents;
	private int motionLeft,motionUp, motionRight, motionDown;

	public MultitouchGestureView(Context context) {
		super(context);
	}
	
	public MultitouchGestureView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		//Find focus of possibly multiple fingers
		int pointerCount = ev.getPointerCount();
		float focusX = 0, focusY = 0; 
		MotionEvent.PointerCoords coords = new MotionEvent.PointerCoords();
		for(int i=0;i<pointerCount;i++){
			ev.getPointerCoords(i, coords);
			focusX += coords.x;
			focusY += coords.y;
		}
		focusX /= pointerCount;
		focusY /= pointerCount;
			
		//Perform action specific stuff
		double motionAngle;
		if(ev.getAction() == MotionEvent.ACTION_DOWN) {
			oneFingerEvents = 0;
			twoFingerEvents = 0;
			moreFingerEvents = 0;

			beginX = focusX;
			beginY = focusY;
			lastX = focusX;
			lastY = focusY;
			
			motionUp = 0;
			motionDown = 0;
			motionLeft = 0;
			motionRight = 0;
		}
		else if (ev.getAction() == MotionEvent.ACTION_MOVE) {
			motionAngle = Math.atan2(lastY - focusY, focusX - lastX); //Get the motion angle
			
			if(-Math.PI/4 < motionAngle && motionAngle <= Math.PI/4) {
				motionRight++;
			}
			else if(Math.PI/4 < motionAngle && motionAngle <= 3*Math.PI/4) {
				motionUp++;
			}
			else if(-3*Math.PI/4 < motionAngle && motionAngle <= -Math.PI/4) {
				motionDown++;
			}
			else {
				motionLeft++;
			}
			lastX = focusX;
			lastY = focusY;
		}
		else if (ev.getAction() == MotionEvent.ACTION_UP) {
			if(FloatMath.sqrt((focusY-beginY)*(focusY-beginY)+(focusX-beginX)*(focusX-beginX)) > 300){
				int globalPointerCount = 0; //The overall pointer count for this gesture
				if(oneFingerEvents > twoFingerEvents + moreFingerEvents)
					globalPointerCount = 1;
				else if(twoFingerEvents > oneFingerEvents + moreFingerEvents)
					globalPointerCount = 2;
				
				int threshold = 4*(motionUp + motionDown + motionLeft + motionRight)/5;
				
				if(motionUp > threshold) //Up gesture
					((MultitouchGestureListener)getContext()).multitouchMotionEvent(globalPointerCount, GestureType.UP);
				else if(motionDown > threshold) //Down gesture
					((MultitouchGestureListener)getContext()).multitouchMotionEvent(globalPointerCount, GestureType.DOWN);
				else if(motionLeft > threshold)  //Left gesture
					((MultitouchGestureListener)getContext()).multitouchMotionEvent(globalPointerCount, GestureType.LEFT);
				else if(motionRight > threshold)  //Right gesture
					((MultitouchGestureListener)getContext()).multitouchMotionEvent(globalPointerCount, GestureType.RIGHT);
			}
		}

		if (ev.getPointerCount() == 1) {
			oneFingerEvents++;
		}
		else if (ev.getPointerCount() == 2) {
			twoFingerEvents++;
		}
		else if (ev.getPointerCount() > 2) {
			moreFingerEvents++;
		}

		return true;
	}
	
}
